import type { ComponentStyleIdType } from '../../../types/interfaces'
import { BaseModule } from '../../../lib/abstract'
import { PageHandler } from '../../../lib/page_handler'
import { IconfontPageType } from '../../../lib/page_handler/platform/iconfont/types'
import { ToolKit } from '../../../lib/utils/toolkit'
import {
  ComponentStyleId,
  HOSTNAME,
  logger,
  SUPPORTED_PLATFORMS,
} from '../../../types/constants'
import { SYMBOLS } from '../../../types/interfaces'
import { ConfigManager } from '../../config_manager'

// 配置类型定义
interface SvgCleanConfig {
  /** 要移除的SVG元素属性 */
  removeSvgAttrs?: string[]
  /** 要移除的path元素属性 */
  removePathAttrs?: string[]
  /** 是否转换双引号为单引号 */
  convertQuotes?: boolean
  /** 是否优化路径标签格式 */
  optimizePathTags?: boolean
  /** 是否移除注释 */
  removeComments?: boolean
  /** 是否压缩多余空格 */
  compressSpaces?: boolean
}

interface Config {
  enabled?: boolean
  cleanConfig?: SvgCleanConfig
}

// 默认清理配置
const DEFAULT_CLEAN_CONFIG: SvgCleanConfig = {
  removeSvgAttrs: [
    't',
    'style',
    'data-spm-click',
    'vclick-ignore',
    'mx-click',
    'mx-focusout',
    'mx-keydown',
    // 与路径属性相同的部分
    'class',
    'p-id',
    'data-spm-anchor-id',
  ],
  removePathAttrs: [
    'class',
    'p-id',
    'data-spm-anchor-id',
  ],
  convertQuotes: true,
  optimizePathTags: true,
  removeComments: true,
  compressSpaces: true,
}

// 测试链接：https://www.iconfont.cn/search/index?searchType=icon
export class SvgCopy extends BaseModule {
  readonly id: string = 'svg_copy'
  readonly styleId: string = ComponentStyleId[this.name]
  isInitialized: boolean = false
  readonly supportedPlatforms: string[] = ConfigManager.getInstance().moduleSupportedPlatforms(this.name)
  private static instance: SvgCopy
  private readonly documentClickEventName = 'click.svg-copy'

  config: Config = {
    enabled: true,
    cleanConfig: DEFAULT_CLEAN_CONFIG,
  }

  get name(): ComponentStyleIdType {
    return 'SvgCopy'
  }

  constructor() {
    super()
  }

  handleCleanupOthers(): void {
    $(document).off(this.documentClickEventName)
  }

  /**
   * 获取单例实例
   */
  public static getInstance(): SvgCopy {
    if (!SvgCopy.instance) {
      SvgCopy.instance = new SvgCopy()
    }
    return SvgCopy.instance
  }

  destroy(): void {
    super.destroy()

    this.unregisterStyle(this.styleId)
  }

  core(): void {
    this.loadConfig()

    if (!this.config.enabled)
      return

    this.copySvg()

    // 注册样式
    this.registerStyle(this.styleId, this.getStyles())
  }

  onToggleCallback(_id: string, checked: boolean): void {
    super.onToggleCallback(_id, checked)
  }

  copySvg(): void {
    $(document).off(this.documentClickEventName).on(this.documentClickEventName, '#btn-copy-svg', async (e) => {
      e.preventDefault()
      e.stopPropagation()

      const $copyBtn = $(e.currentTarget)
      const $svg = $copyBtn.closest('.download-dialog').find('.download-content .stage svg')

      if (!$svg || !$svg.length)
        return

      try {
        const svgElement = $svg[0]
        const optimizedSvg = this.optimizeSvg(svgElement.outerHTML)

        await ToolKit.ui.clipboard.copyToClipboard(optimizedSvg)
      }
      catch (error) {
        logger.error(`[${this.name}] SVG 复制失败:`, error)
      }
    })
  }

  /**
   * 优先 DOM 解析，失败时使用正则
   */
  private optimizeSvg(svgCode: string): string {
    try {
      return this.optimizeSvgWithDOM(svgCode)
    }
    catch (error) {
      logger.debug(`[${this.name}] DOM 解析失败，使用正则优化`, error)
      return this.optimizeSvgWithRegex(svgCode)
    }
  }

  /**
   * DOM 解析优化
   */
  private optimizeSvgWithDOM(svgCode: string): string {
    const { cleanConfig = DEFAULT_CLEAN_CONFIG } = this.config
    const parser = new DOMParser()
    const doc = parser.parseFromString(svgCode, 'image/svg+xml')

    if (doc.querySelector('parsererror'))
      throw new Error('SVG 解析错误')

    const svgElement = doc.documentElement

    // 移除 SVG 属性
    cleanConfig.removeSvgAttrs?.forEach((attr) => {
      svgElement.removeAttribute(attr)
    })

    // 移除 path 属性
    doc.querySelectorAll('path').forEach((path) => {
      cleanConfig.removePathAttrs?.forEach((attr) => {
        path.removeAttribute(attr)
      })
    })

    const result = new XMLSerializer().serializeToString(svgElement)
    return this.applyTextOptimizations(result, cleanConfig)
  }

  /**
   * 正则表达式优化
   */
  private optimizeSvgWithRegex(svgCode: string): string {
    const { cleanConfig = DEFAULT_CLEAN_CONFIG } = this.config
    let result = svgCode

    // 移除 SVG 元素属性
    if (cleanConfig.removeSvgAttrs?.length) {
      cleanConfig.removeSvgAttrs.forEach((attr) => {
        // 使用单词边界确保精确匹配
        result = result.replace(new RegExp(`\\s+\\b${attr}\\b="[^"]*"`, 'g'), '')
      })
    }

    // 移除 path 元素属性
    if (cleanConfig.removePathAttrs?.length) {
      cleanConfig.removePathAttrs.forEach((attr) => {
        result = result.replace(new RegExp(`(<path[^>]*?)\\s+\\b${attr}\\b="[^"]*"([^>]*>)`, 'g'), '$1$2')
      })
    }

    return this.applyTextOptimizations(result, cleanConfig)
  }

  /**
   * 应用文本优化
   */
  private applyTextOptimizations(svgCode: string, cleanConfig: SvgCleanConfig): string {
    let result = svgCode

    if (cleanConfig.convertQuotes)
      result = result.replace(/"/g, '\'')

    if (cleanConfig.optimizePathTags)
      result = result.replace(/><\/path>/g, '/>')

    if (cleanConfig.removeComments)
      result = result.replace(/<!--[\s\S]*?-->/g, '')

    if (cleanConfig.compressSpaces)
      result = result.replace(/\s+/g, ' ').trim()

    return result
  }

  applyConfig(config: Partial<Config>): void {
    super.updateConfig(config)

    this.copySvg()

    logger.info(`[${this.name}] Config updated and apply`, this.config)
  }

  iconfontStyles(): string {
    return HOSTNAME === SUPPORTED_PLATFORMS.ICONFONT && PageHandler.getCurrentPageType() === IconfontPageType.SearchIcon
      ? `
  #btn-copy-svg::after {
    content: '${SYMBOLS.STATUS.SPARKLES}';
  }
`
      : ''
  }

  getStyles(): string {
    return `
    ${this.iconfontStyles()}
    `
  }
}
